﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;

using JavaSubstitutes;

namespace Sprites
{
	public class BgRenderer
	{
		private int CameraX, CameraY;
		private WriteableBitmap wBGbmp;
		protected Canvas bgCanvas;
		private static Color transparent = Color.FromArgb(0, 0, 0, 0);
		public Level Level; //meliot: made public for testing

		private int Width;
		private int Height;
		private int Distance;

		protected GraphicsConfiguration GraphicsConfiguration;

		public BgRenderer(Level level, GraphicsConfiguration graphicsConfiguration, int width, int height, int distance)
		{
			Distance = distance;
			Width = width;
			Height = height;

			GraphicsConfiguration = graphicsConfiguration;

			Level = level;
			wBGbmp = graphicsConfiguration.createCompatibleImage(width, height, Transparency.BITMASK); //todo: we dont' really need the graphicsConfiguration class...
			bgCanvas = new Canvas() { Width = width, Height = height, Background = Colors.Transparent.ToBrush() };

			updateArea(0, 0, width, height, CameraX, CameraY);
		}

		public void setCam(int xCam, int yCam)
		{
			xCam /= Distance;
			yCam /= Distance;
			//Debug.WriteLine("xCam/yCam: " + xCam.ToString() + ", " + yCam.ToString());

			int xCamDelta = CameraX - xCam,
				yCamDelta = CameraY - yCam;

			CameraX = xCam;
			CameraY = yCam;

			if (xCamDelta < 0)
			{
				//meliot: if it enters here, it means the background needs to scroll to the LEFT, meaning mario advances to the right
				if (xCamDelta < -Width) xCamDelta = -Width;

				updateArea(Width + xCamDelta, 0, -xCamDelta, Height, CameraX, CameraY);
			}
			else if (xCamDelta > 0)
			{
				if (xCamDelta > Width) xCamDelta = Width;

				updateArea(0, 0, xCamDelta, Height, CameraX, CameraY);
			}

			if (yCamDelta < 0)
			{
				if (yCamDelta < -Width) yCamDelta = -Width;

				updateArea(0, Height + yCamDelta, Width, -yCamDelta, CameraX, CameraY);
			}
			else if (yCamDelta > 0)
			{
				if (yCamDelta > Width) yCamDelta = Width;

				updateArea(0, 0, Width, yCamDelta, CameraX, CameraY);
			}
		}


		//protected virtual void ShiftX(int xCamDelta)
		//{
		//    if (xCamDelta == 0) return;
		//    //Debug.WriteLine(String.Format("XCamDelta: {0}", xCamDelta));

		//    wBGbmp.Render(bgCanvas, null); bgCanvas.Children.Clear();

		//    foreach (UIElement elem in bgCanvas.Children)
		//        Canvas.SetLeft(elem, Canvas.GetLeft(elem) + xCamDelta);

		//}

		//protected virtual void ShiftY(int yCamDelta)
		//{
		//    if (yCamDelta == 0) return;
		//    foreach (UIElement elem in bgCanvas.Children)
		//        Canvas.SetTop(elem, Canvas.GetTop(elem) + yCamDelta);
		//}


		public void updateArea(int x0, int y0, int w, int h, int cameraX, int cameraY)
		{
			if (Art.bg == null) return; //hasn't loaded yet

			bgCanvas.Children.Clear();

			int xTileStart = (x0 + cameraX) / 32;
			int yTileStart = (y0 + cameraY) / 32;
			int xTileEnd = (x0 + cameraX + w) / 32;
			int yTileEnd = (y0 + cameraY + h) / 32;
			for (int x = xTileStart; x <= xTileEnd; x++)
			{
				for (int y = yTileStart; y <= yTileEnd; y++)
				{
					int b = Level.getBlock(x, y) & 0xff;

					Image img = new Image() { Source = new BitmapImage(((BitmapImage)Art.bg[b % 8, b / 8].Source).UriSource) { CreateOptions = BitmapCreateOptions.None } };
					bgCanvas.Children.Add(img);
					Canvas.SetLeft(img, (x << 5) - cameraX);
					Canvas.SetTop(img, (y << 5) - cameraY - 16);
				}
			}
		}

		public void render(WriteableBitmap wbmp, int tick, double alpha)
		{
			//draw it then save it
			updateArea(0, 0, Width, Height, CameraX, CameraY);
			wbmp.Render(bgCanvas, null);


		}

		public void setLevel(Level level)
		{
			Level = level;
			updateArea(0, 0, Width, Height, CameraX, CameraY);
		}
	}
}

